package com.yxsk.relay.job.admin.web.common.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.yxsk.relay.job.admin.web.common.enums.ResultEnum;
import com.yxsk.relay.job.admin.web.common.exception.RelayAdminWebRuntimeException;
import com.yxsk.relay.job.component.common.utils.DateUtils;
import org.springframework.util.StringUtils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.util.Calendar;

/**
 * @author 小懒虫
 * @date 2019/4/9
 */
public class JwtUtil {

    public static final String TOKEN_NAME_OF_COOKIE = "Authorization";

    /**
     * 生成JwtToken
     *
     * @param userId 用户Id
     * @param secret 秘钥, 加密后的密码
     * @param amount 过期天数
     */
    public static String getToken(String userId, String secret, int amount) {
        // 过期时间
        Calendar ca = Calendar.getInstance();
        ca.add(Calendar.DATE, amount);

        // 随机Claim
        String random = ToolUtil.getRandomString(6);

        // 创建JwtToken对象
        String token = "";
        token = JWT.create()
                .withSubject(userId)    // 用户名
                .withIssuedAt(DateUtils.getCurrentDate())           // 发布时间
                .withExpiresAt(ca.getTime())        // 过期时间
                .withClaim("ran", random)     // 自定义随机Claim
                .sign(getSecret(random));

        return token;
    }

    /**
     * 获取请求对象中的token数据
     */
    public static String getRequestToken(HttpServletRequest request) {
        // 获取JwtTokens失败
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if (TOKEN_NAME_OF_COOKIE.equals(cookie.getName())) {
                    String authorization = cookie.getValue();
                    if (StringUtils.hasLength(authorization)) {
                        return authorization;
                    }
                }
            }
        }
        throw new RelayAdminWebRuntimeException(ResultEnum.TOKEN_ERROR);
    }

    /**
     * 解析JwtToken，生成用户对象
     *
     * @param token JwtToken数据
     */
    public static String getUserIdFromToken(String token) {
        return JWT.decode(token).getSubject();
    }

    /**
     * 验证JwtToken
     *
     * @param token JwtToken数据
     * @return true 验证通过
     * @throws TokenExpiredException    Token过期
     * @throws JWTVerificationException 令牌无效（验证不通过）
     */
    public static void verifyToken(String token) throws JWTVerificationException {
        String ran = JWT.decode(token).getClaim("ran").asString();
        JWTVerifier jwtVerifier = JWT.require(getSecret(ran)).build();
        jwtVerifier.verify(token);
    }

    /**
     * 生成Secret混淆数据
     */
    private static Algorithm getSecret(String random) {
        return Algorithm.HMAC256(random);
    }
}
